(function($) {
	var aux = {
		// navigates left / right
		navigate : function(dir, $el, $wrapper, opts, cache) {

			var scroll = opts.scroll, factor = 1, idxClicked = 0;

			if (cache.expanded) {
				scroll = 1; // scroll is always 1 in full mode
				factor = 3; // the width of the expanded item will be 3 times
							// bigger than 1 collapsed item
				idxClicked = cache.idxClicked; // the index of the clicked item
			}

			// clone the elements on the right / left and append / prepend them
			// according to dir and scroll
			if (dir === 1) {
				$wrapper.find('div.ca-item:lt(' + scroll + ')').each(
						function(i) {
							$(this).clone(true).css(
									'left',
									(cache.totalItems - idxClicked + i)
											* cache.itemW * factor + 'px')
									.appendTo($wrapper);
						});
			} else {
				var $first = $wrapper.children().eq(0);

				$wrapper.find(
						'div.ca-item:gt(' + (cache.totalItems - 1 - scroll)
								+ ')').each(
						function(i) {
							// insert before $first so they stay in the right
							// order
							$(this).clone(true).css(
									'left',
									-(scroll - i + idxClicked) * cache.itemW
											* factor + 'px').insertBefore(
									$first);
						});
			}

			// animate the left of each item
			// the calculations are dependent on dir and on the cache.expanded
			// value
			$wrapper
					.find('div.ca-item')
					.each(
							function(i) {
								var $item = $(this);
								$item
										.stop()
										.animate(
												{
													left : (dir === 1) ? '-='
															+ (cache.itemW
																	* factor * scroll)
															+ 'px'
															: '+='
																	+ (cache.itemW
																			* factor * scroll)
																	+ 'px'
												},
												opts.sliderSpeed,
												opts.sliderEasing,
												function() {
													if ((dir === 1 && $item
															.position().left < -idxClicked
															* cache.itemW
															* factor)
															|| (dir === -1 && $item
																	.position().left > ((cache.totalItems - 1 - idxClicked)
																	* cache.itemW * factor))) {
														// remove the item that
														// was cloned
														$item.remove();
													}
													cache.isAnimating = false;
												});
							});

		},
		// opens an item (animation) -> opens all the others
		openItem : function($wrapper, $item, opts, cache) {
			cache.idxClicked = $item.index();
			// the item's position (1, 2, or 3) on the viewport (the visible
			// items)
			cache.winpos = aux.getWinPos($item.position().left, cache);
			$wrapper.find('div.ca-item').not($item).hide();
			$item.find('div.ca-content-wrapper')
					.css('left', cache.itemW + 'px').stop().animate({
						width : cache.itemW * 2 + 'px',
						left : cache.itemW + 'px'
					}, opts.itemSpeed, opts.itemEasing).end().stop().animate({
						left : '0px'
					}, opts.itemSpeed, opts.itemEasing, function() {
						cache.isAnimating = false;
						cache.expanded = true;

						aux.openItems($wrapper, $item, opts, cache);
					});

		},
		// opens all the items
		openItems : function($wrapper, $openedItem, opts, cache) {
			var openedIdx = $openedItem.index();

			$wrapper.find('div.ca-item').each(
					function(i) {
						var $item = $(this), idx = $item.index();

						if (idx !== openedIdx) {
							$item.css(
									'left',
									-(openedIdx - idx) * (cache.itemW * 3)
											+ 'px').show().find(
									'div.ca-content-wrapper').css({
								left : cache.itemW + 'px',
								width : cache.itemW * 2 + 'px'
							});

							// hide more link
							aux.toggleMore($item, false);
						}
					});
		},
		// show / hide the item's more button
		toggleMore : function($item, show) {
			(show) ? $item.find('a.ca-more').show() : $item.find('a.ca-more')
					.hide();
		},
		// close all the items
		// the current one is animated
		closeItems : function($wrapper, $openedItem, opts, cache) {
			var openedIdx = $openedItem.index();

			$openedItem.find('div.ca-content-wrapper').stop().animate({
				width : '0px'
			}, opts.itemSpeed, opts.itemEasing).end().stop().animate({
				left : cache.itemW * (cache.winpos - 1) + 'px'
			}, opts.itemSpeed, opts.itemEasing, function() {
				cache.isAnimating = false;
				cache.expanded = false;
			});

			// show more link
			aux.toggleMore($openedItem, true);

			$wrapper.find('div.ca-item').each(
					function(i) {
						var $item = $(this), idx = $item.index();

						if (idx !== openedIdx) {
							$item.find('div.ca-content-wrapper').css({
								width : '0px'
							}).end().css(
									'left',
									((cache.winpos - 1) - (openedIdx - idx))
											* cache.itemW + 'px').show();

							// show more link
							aux.toggleMore($item, true);
						}
					});
		},
		// gets the item's position (1, 2, or 3) on the viewport (the visible
		// items)
		// val is the left of the item
		getWinPos : function(val, cache) {
			switch (val) {
			case 0:
				return 1;
				break;
			case cache.itemW:
				return 2;
				break;
			case cache.itemW * 2:
				return 3;
				break;
			}
		}
	}, methods = {
		init : function(options) {

			if (this.length) {

				var settings = {
					sliderSpeed : 500, // speed for the sliding animation
					sliderEasing : 'easeOutExpo',// easing for the sliding
													// animation
					itemSpeed : 500, // speed for the item animation (open /
										// close)
					itemEasing : 'easeOutExpo',// easing for the item animation
												// (open / close)
					scroll : 1
				// number of items to scroll at a time
				};

				return this
						.each(function() {

							// if options exist, lets merge them with our
							// default settings
							if (options) {
								$.extend(settings, options);
							}

							var $el = $(this), $wrapper = $el
									.find('div.ca-wrapper'), $items = $wrapper
									.children('div.ca-item'), cache = {};

							// save the with of one item
							cache.itemW = $items.width();
							// save the number of total items
							cache.totalItems = $items.length;

							// add navigation buttons
							if (cache.totalItems > 3)
								$el
										.prepend('<div class="ca-nav"><span class="ca-nav-prev">Previous</span><span class="ca-nav-next">Next</span></div>')

								// control the scroll value
							if (settings.scroll < 1)
								settings.scroll = 1;
							else if (settings.scroll > 3)
								settings.scroll = 3;

							var $navPrev = $el.find('span.ca-nav-prev'), $navNext = $el
									.find('span.ca-nav-next');

							// hide the items except the first 3
							$wrapper.css('overflow', 'hidden');

							// the items will have position absolute
							// calculate the left of each item
							$items.each(function(i) {
								$(this).css({
									position : 'absolute',
									left : i * cache.itemW + 'px'
								});
							});

							// click to open the item(s)
							$el.find('a.ca-more').live(
									'click.contentcarousel',
									function(event) {
										if (cache.isAnimating)
											return false;
										cache.isAnimating = true;
										$(this).hide();
										var $item = $(this).closest(
												'div.ca-item');
										aux.openItem($wrapper, $item, settings,
												cache);
										return false;
									});

							$el.find('.ca-icon').live(
									'click.contentcarousel',
									function(event) {
										if (cache.isAnimating)
											return false;
										cache.isAnimating = true;
										// $(this).hide();
										var $item = $(this).closest(
												'div.ca-item');
										aux.openItem($wrapper, $item, settings,
												cache);
										return false;
									});

							// click to close the item(s)
							$el.find('a.ca-close').live(
									'click.contentcarousel',
									function(event) {
										if (cache.isAnimating)
											return false;
										cache.isAnimating = true;
										var $item = $(this).closest(
												'div.ca-item');
										aux.closeItems($wrapper, $item,
												settings, cache);
										return false;
									});

							// navigate left
							$navPrev.bind('click.contentcarousel', function(
									event) {
								if (cache.isAnimating)
									return false;
								cache.isAnimating = true;
								aux
										.navigate(-1, $el, $wrapper, settings,
												cache);
							});

							// navigate right
							$navNext.bind('click.contentcarousel',
									function(event) {
										if (cache.isAnimating)
											return false;
										cache.isAnimating = true;
										aux.navigate(1, $el, $wrapper,
												settings, cache);
									});

							// adds events to the mouse
							$el.bind('mousewheel.contentcarousel', function(e,
									delta) {
								if (delta > 0) {
									if (cache.isAnimating)
										return false;
									cache.isAnimating = true;
									aux.navigate(-1, $el, $wrapper, settings,
											cache);
								} else {
									if (cache.isAnimating)
										return false;
									cache.isAnimating = true;
									aux.navigate(1, $el, $wrapper, settings,   // 1,-1은 디렉
											cache);
								}
								return false;
							});

						});
			}
		}
	};

	$.fn.contentcarousel = function(method) {		
		if (methods[method]) {
			return methods[method].apply(this, Array.prototype.slice.call(
					arguments, 1));
		} else if (typeof method === 'object' || !method) {
			return methods.init.apply(this, arguments);
		} else {
			$.error('Method ' + method
					+ ' does not exist on jQuery.contentcarousel');
		}
	};

})(jQuery);